<?php
/**
 * Database objects
 * All In One :)
 */

/**
 * @ignore 
 */
if( defined("apl_".__FILE__)) return;
define("apl_".__FILE__,"apl_".__FILE__);
require_once(APL_ROOT.'/apl_constants.php');


 /**
  * Base Connection Class
  * Responsible for database connection
  * @package apl
  * @subpackage database
*/
class AplConnection{
	private $hDb;
	
	 /**
	  *	Opens a connection to the database , any instance of the class is parameter
	  * to an instance or subclass of AplDb .
	  */
	function __construct($ServerName,$UserName,$Password,$DatabaseName)
	{
		$this->hDb = mysql_connect($ServerName,$UserName,$Password,true);

		if(!$this->hDb )
		{
			throw new Exception( aplTranslate( EX_DB_CONNECT_ERROR ) ,EX_DB_CONNECT_ERROR);
		}
		if( !mysql_selectdb($DatabaseName,$this->hDb) )
			throw new Exception( aplTranslate( EX_DB_SELECT_ERROR ) ,EX_DB_SELECT_ERROR);
	}
	
	public function getDbHandle()
	{
		return $this->hDb;
	}
	
	public function destroyObject()
	{
		if( is_resource($this->hDb))
		{
			mysql_close( $this->hDb );
			$this->hDb = null;
		}		
	}
	/**
	 *	closes the active connection
	 */
	function __destruct()
	{
		if( is_resource($this->hDb))
		{
			mysql_close( $this->hDb );
			$this->hDb = null;
		}

	}
}

/**
  * Basic Database Object
  *	Responsible for basic sql tasks ( insert,update,delete,Select ) and 
  * base class for other database related classes
  * fields and values must bechecked against attacks such as sql injection
  * apl is not responsible for that ;)
  * 
  *	@package apl
  *	@subpackage database
  */
class AplDb{
	protected $hDb;
	protected $LastinsertID;
	/**
	  *	Connection object is passed by parameter
	  * @param AplConnection $ConnectionObject
	  */
	function __construct( &$ConnObj ){
		$this->hDb = $ConnObj;
	}

	function __destruct()
	{
		$this->hDb = null;
	}
	/**
	  *	Executes a query
	  * @param String $qry :Query to execute
	  *	@return ResultSet
	  */
	protected function execute( $qry )
	{
		/* Set query as Default charset*/
		mysql_query( "SET NAMES '".MYSQL_QUERY_CHARSET."'", $this->hDb->getDbHandle());
		$ResultSet = @mysql_query( $qry,$this->hDb->getDbHandle());
		if( mysql_errno( $this->hDb->getDbHandle())  )
		{
			throw new Exception( aplTranslate(EX_DB_QUERY_EXECUTION_FAILED).mysql_error(),EX_DB_QUERY_EXECUTION_FAILED);
		}
		else
			return $ResultSet;
		
	}
	
	/**
	 * Inserts a row
	 * @param String $tableName : Name of table to insert
	 * @param Array $fields : array of string containing the column names of the table
	 * @param Array $Values : array of string containing values to insert table
	 */
	protected function insert( $tableName,$fields,$Values)
	{
		$qry="insert INTO ".$tableName."(";
		if( count($fields) <> count($Values) )
		{
			throw new Exception( aplTranslate(EX_PRM_NOT_VALID) ,EX_PRM_NOT_VALID);
		}
	
		foreach($fields as $key => $val )
			$qry = $qry.$val.",";
		
		$qry=substr( $qry,0,strlen($qry)-1).") VALUES(";
		foreach( $Values as $key => $val )
		{
			$val = mysql_escape_string( $val );
			$qry = $qry."'".$val."',";
		}

		$qry=substr( $qry,0,strlen($qry)-1).")";
		$this->execute($qry);
		$this->LastinsertID = mysql_insert_id($this->hDb->getDbHandle());
		return $this->LastinsertID;
	}
	 /**
	  *	Updates one or more rows in a table 
	  * @param String $tableName : Name of table to insert
	  *	@param Array $fields : array of string containing the column names of the table
	  *	@param Array $Values : array of string containing values to insert table
	  *	@param String $WhereClause : Optional where clause
	  */

	protected function update($tableName,$fields,$Values,$WhereClause=null)
	{
		$qry = "update ".$tableName." SET ";
		for( $i = 0; $i<count($fields);$i++)
			$qry = $qry." ".$fields[$i]."='".$Values[$i]."',";
		$qry=substr( $qry,0,strlen($qry)-1);
		if( isset($WhereClause) )
			$qry=$qry." WHERE ".$WhereClause;
		$this->execute( $qry );
	}
	/**
	 *	deletes one or more rows from table
	 * @param String $tableName 	: Name of table to insert
	 *	@param String $WhereClause 	: Where Clause
	*/
	protected function delete($tableName,$WhereClause)
	{
		$qry = "delete FROM ".$tableName;
		if( isset($WhereClause) )
			$qry = $qry." WHERE ".$WhereClause;
		$this->execute( $qry );
	}
}

/**
 *	Simple Dataset Class
 *	Base class for "select and display" tasks.
 *	@package apl
 *	@subpackage database
 */

	class AplQuery extends AplDb
	{
		private $Query;
		private $RowsPerPage;
		private $PageCount;
		private $ActivePage;
		private $tableData;
		private $rowNumber;
	
		function __construct( &$objConn )
		{
			parent::__construct( $objConn );
			$this->PageCount =0;
			$this->ActivePage = 0;
		}
	
		function __destruct()
		{
			parent::__destruct();
		}
		function getLimitClause()
		{
			if( $this->PageCount == 0 )
				return NULL;
			return " LIMIT ". ( ($this->ActivePage-1)*$this->RowsPerPage).",".$this->RowsPerPage;
		}
	     /**
         * returns a new AplQuery Object
         * not a clone 
         */
         public function derive(){
             $obj = new AplQuery( $this->hDb );
             return $obj;             
         }
		 /**
		  *	Opens a query and prepares the object for future operations
		  * @param String $qryData : Query to execute 
		  *	@param Integer $rowsPerPage : Maximum number of rows per page
		  * @param Integer $pageIdx : page of rows will be selected
		  */
		public function open( $qryData,$rowsPerPage=1,$pageIdx=1)
		{
	        $this->close();
			if( $this->PageCount == 0 )
			{
				try{
					$result = parent::execute( "SELECT COUNT(*) FROM (".$qryData.") BtblCount"  );
				}catch( Exception $e)
				{
					throw new Exception( $e->getMessage(),$e->getCode());
				}
				$rowData = mysql_fetch_array( $result, MYSQL_NUM );
				if( $rowData[0] == 0 )
					throw new Exception( aplTranslate(EX_DB_NO_ROWS),EX_DB_NO_ROWS);
	
				mysql_free_result( $result );
				$this->RowsPerPage = $rowsPerPage;
				$this->Query = $qryData;
				
				$this->PageCount = ceil( ($rowData[0]) / $this->RowsPerPage );
				$this->	ActivePage = $pageIdx;
				$this->tableData = parent::execute( $qryData. $this->getLimitClause());
				$this->rowNumber=1;
			}
			else
			{
				throw new Exception( aplTranslate( EX_INVALID_OBJECT_STATE ),EX_INVALID_OBJECT_STATE);
			}
	
		}
		/**
		 *	Closes the active query
		 */
		public function close()
		{
			if( isset($this->tableData) )
				@mysql_free_result( $this->tableData );
			$this->PageCount = 0;
			$this->ActivePage = 0;
		}
		/**
		 *	Fetches the data of current row
		 *	@return Array
		 */
		public function fetch()
		{
			if($this->rowNumber == 0)
				return false;
			mysql_data_seek( $this->tableData, $this->rowNumber-1);
			$rtnArray =  mysql_fetch_array( $this->tableData,MYSQL_BOTH );
			return $rtnArray;
		}
		/**
	     *	Moves pointer to previous record :)
		 *	@return  True|False
		 */
		function previousRecord()
		{
			if( $this->rowNumber > 1 )
			{
				$this->rowNumber-=1;
				return true;
			}
			else 
				return  false;
		}
		/**
		 *	Moves pointer to next record :)
		 *	@return  True|False
		 */
		function nextRecord()
		{
	
			if( $this->rowNumber < mysql_num_rows( $this->tableData) )
			{
				$this->rowNumber+=1;
				return true;
			}
			else return false;
		}
		/**
		 *	Fetches the previous page from query
		 *	@return  True|False
		 */
		function previousPage()
		{
			if( $this->PageCount == 0 )
			{
				throw new Exception( aplTranslate(EX_INVALID_OBJECT_STATE), EX_INVALID_OBJECT_STATE);
			}
			if( $this->ActivePage == 1 )
				return false;
	
			$this->ActivePage-=1;
			mysql_free_result( $this->tableData);
			$this->tableData = parent::execute( $this->Query. $this->getLimitClause());
			return true;
		}
		/**
		 * Fetches the next page from query
		 * @return  True|False
		 */
		function nextPage()
		{
			if( $this->PageCount == 0 )
			{
				throw new Exception( aplTranslate( EX_INVALID_OBJECT_STATE ),EX_INVALID_OBJECT_STATE);
			}
			if( $this->ActivePage == $this->PageCount )
				return false;
	
			$this->ActivePage+=1;
			mysql_free_result( $this->tableData);
			$this->tableData = parent::execute( $this->Query. $this->getLimitClause());
			$this->rowNumber = 1;
			return true;
		}
		/**
		 * Moves pointer to First Record;
		 */
		function firstRecord()
		{
			if( $this->PageCount == 0)
			{
				return;
			}
			$this->rowNumber = 1;
		}
		/**
		 *	Moves pointer to Last Record
		 */
		function lastRecord()
		{
			if( $this->PageCount == 0)
			{
				return;
			}
			while( $this->NextRecord() );
		}
		 /**
		  *	Determines the end of dataset has come or not
		  *	@return True|False
		  */
		 function eof()
		 {
		 	return ( $this->rowNumber == mysql_num_rows( $this->tableData))	;
		 }
		 /**
		  *	Determines whether we are at  the beginning of dataset  or not
		  *	@return True|False
		  */
		 function bof()
		 {
		 	return !$this->Eof();
		 }
		/**
		 *	Returns the Active Page Number
		 *	@return  Integer
		 */
		function activePage()
		{
			return $this->ActivePage;
		}
		/**
		 *	Returns the PageCount of the executed query
		 *	@return  Integer
		 */
		function pageCount()
		{
			return $this->PageCount;
		}
		/**
		 * Returns the record count of the current page
		 * @return  Integer
		 */
		function recordCount()
		{
			return mysql_num_rows( $this->tableData );
		}
		/**
		 * Returns the active record number of the current page
		 * @return  Integer
		 */
		function recordIndex()
		{
			return $this->rowNumber;
		}
		 /**
		  *	Returns the number of fields that  query fetched
		  *	@return Integer
		  */
		 function getFieldCount()
		 {
		 	return mysql_num_fields( $this->tableData);
		 }
		  /**
		   *	Returns information about the field
		   * 	Return value is an object containing field information
		   * 	Properties of this object can be found in PHP Manual
		   *	@param Integer $fldIndex
		   *	@return Array
		   */
		 function getFieldInfo($fldIndex)
		 {
		 	return mysql_fetch_field($this->tableData,$fldIndex);
		 }		 
		 /**
		  * returns the last value of autoincrement field
		  */
		 public function getLastinsertID()
		 {
		 	return $this->LastinsertID;
		 }
		 /**
		  * Calls parent insert function
		  */
		 public function insert($tblName, $fields,$Values )
		 {
		 	return parent::insert( $tblName , $fields, $Values );
		 }
		 /**
		  * Call parent update function
		  */
		 public function update($tableName,$fields,$Values,$WhereClause=null)
		 {
		 	parent::update($tableName,$fields,$Values,$WhereClause);
		 }
		 /**
		  * Calls parent delete function
		  */
		 public function delete($tableName,$WhereClause)
		 {
		 	parent::delete($tableName,$WhereClause);
		 }
		 /**
		  * Call parent execute function
		  */
		 public function execute( $qry )
		 {
		 	parent::execute($qry);
		 }
	}

?>